/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG                        *
*Copyright (C) 2006, Tony Sparks                                                     *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once
#include "../shared/MFile.h"
#include "../EventManager.h"
#include <iostream>
#include <string>
#include <map>


// max dialog response options
enum E_Responses
{
    D_RESPONSE1 = 0,
    D_RESPONSE2,
    D_RESPONSE3,

    D_MAX_RESPONSES
};

/**
====================================
Possible Responses to a NPC Dialog
====================================
*/
struct DialogResponse
{
    DialogResponse() { size = 0; };

    // mission responses ( it is a response,
    // but might carry a mission name with it )
    struct MissionResponse {
        std::string response;
        std::string mission_name;
        bool        hasMission;
    };
    /** Add a response to the possibilities */
    void Add( const DialogResponse::MissionResponse &res ) { 
        if ( size >= 4 ) return;
        m_responsePossibilites[size++] = res;
    };


    // responses options
    MissionResponse m_responsePossibilites[D_MAX_RESPONSES];
    // how many there are - max 3
    int size;
};

/**
====================================
Event for adding a dialog response
====================================
*/
struct DialogEvent : public IEventData
{   DialogEvent(int response, std::string &m, unsigned int id) : m_response(response), mission(m), ent_id(id) { };
    int m_response;
    std::string mission;
    unsigned int ent_id;
    IEventData* Copy() { return new DialogEvent(m_response, mission, ent_id); };
    virtual ~DialogEvent() {IEventData::~IEventData(); };
};

/**
====================================
Dialog Tree - What the NPC says,
and the possible users response

====================================
*/
class DialogTree
{
public:
    DialogTree();
    virtual ~DialogTree();
    /** Have we talked with this char before? */
    bool TalkedTo() { return m_talkedWith; };
    /** Decide if we talked with them */
    void SetTalkWith( bool b ) { m_talkedWith = b; };

    /** Set the Dialog Tree for each response 
     *  This builds the DialogResponse
     */
    void SetDialogTree( const DialogResponse::MissionResponse &response /*const std::string &response*/, DialogTree* display ) {
        m_responses.Add( response );
        m_dialog[ response.response ] = display;
    };

    /** Set the text for this Node */
    void SetText(const std::string &text) { m_text = text; };
    /** Get this Nodes Text */
    std::string GetText() { return m_text; };
    /** Get this Nodes possible player responses */
    DialogResponse& GetResponses() { return m_responses; };
    /** User made a decision, now return the response tree */
    DialogTree* Respond( const std::string &response );

    void Print() {
        type_DialogNode::iterator it = m_dialog.begin();
        for(;it != m_dialog.begin(); it++)
            std::cout << "PRINTING: " << it->second->GetText() << "\n";
    }

private:
    // conversation tree
    typedef std::map<std::string, DialogTree*> type_DialogNode;
    // possible other dialogs
    type_DialogNode m_dialog;

    // User options as response
    DialogResponse m_responses;

    // this nodes text to print in dialog box
    std::string m_text;

    // did the NPC talk with this dialog
    bool    m_talkedWith;

};

/**
====================================
Model data - holds a dialog tree
====================================
*/
class MModel
{
public:
    MModel(void);

    /** Load a conversation from a file */
    bool LoadDialog( const std::string &file );
    /** Test if this should be displayed */
    bool Active() { return m_active; };
    /** Toggle display */
    void SetActive(bool b) { m_active = b; };
    /** Clear the dialog box of any text */
    void Clear();
    /** Set the contents of the box */
    void SetText(const std::string &s) { m_text = s; };

    /** Set the current Dialog node */
    void SetDialogTree( DialogTree* current );

    /** Current Text to Display in dialog area*/
    std::string GetText() { return m_text; };

    /** Number of responses */
    int GetNumberOfResponses() {
        if ( m_currentDialog )
            return m_currentDialog->GetResponses().size;
        return 0;
    };

    /** Current Possible Responses to display in response area */
    DialogResponse* GetResponses() {
        if ( m_currentDialog )
            return &m_currentDialog->GetResponses();
        return NULL;
    };

    /** Respond to the NPC */
    void Respond( const std::string &st ) {
        if ( m_currentDialog )
        {
            SetDialogTree ( m_currentDialog->Respond( st ) );
        }
    };

    /** The current Resonponse Option */
    int     GetIndex() { return m_index; };
    /** Set the current response Option */
    void    SelectNextResponse();
    /** Get the prev response */
    void    SelectPrevResponse();

private:
   
    /** Recusevily read the dialog tree */
    DialogTree* ReadDialog( DialogTree* root, MFile &f );


    // the dialog tree root node
    DialogTree* m_currentDialog;
    DialogTree* m_root; // capture the root, so we can delete all the children

    // current text to display
    std::string m_text;

    // show the dialog box
    bool    m_active;

    // current Option
    int     m_index;
public:
    virtual ~MModel(void);
};
